home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 12 - 1996 / 12.05 May 96 / Challenge.p < prev    next >
Encoding:
Text File  |  1996-03-05  |  3.9 KB  |  144 lines  |  [TEXT/CWIE]

  1. unit Challenge;
  2.  
  3. interface
  4.  
  5.     uses
  6.         Types;
  7.     
  8.     type
  9.         CharsArray = packed array[0..0] of byte;
  10.         CharsArrayPtr = ^CharsArray;
  11.         
  12.     procedure ReverseTheWords( text: CharsArrayPtr; numCharsIn: longint );
  13.  
  14. implementation
  15.  
  16.     uses
  17.         Memory;
  18.  
  19. {
  20.     Author: Peter N Lewis <peter@stairways.com.au>
  21.     
  22.     This is not really optimal, I felt compelled to send in a Pascal solution since I was
  23.     one of the people who complained about the language bias.  I didn’t have time to do 
  24.     this challenge justice.
  25.     
  26.     Method:
  27.     
  28.     Allocate a block of memory equal in size to numCharsIn (if numCharsIn < 2048, we
  29.     short circuit this to use a block of memory on the stack).
  30.     
  31.     Initialize a 0..255 array to determine whether a character is  an alphanum (I could
  32.     just use the ANSI ctype.p file, but without a macro call, there is a pretty big hit).
  33.     
  34.     reverse the words from the source to our new buffer.  We move in from both ends,
  35.     copying non-alphanums, and then swapping words and fixing the case.
  36.     
  37.     BlockMoveData the buffer back to the source buffer.
  38.     
  39.     Release the memory if we allocated any.
  40. }
  41.  
  42.     procedure ReverseTheWords( text: CharsArrayPtr; numCharsIn: longint );
  43.         const
  44.             stack_space_size = 2048;
  45.         var
  46.             space: packed array[0..stack_space_size] of byte;
  47.             buffer: CharsArrayPtr;
  48.             memory: Handle;
  49.             leftin, leftout, rightin, rightout, leftedge, rightedge: longint;
  50.             i: longint;
  51.             leftchar, rightchar: integer;
  52.             alphanum_set:array[0..255] of Boolean;
  53.     begin
  54.         { allocate memory if needed }
  55.         if numCharsIn < stack_space_size then begin
  56.             memory := nil;
  57.             buffer := @space;
  58.         end else begin
  59.             memory := NewHandle( numCharsIn );
  60.             if memory = nil then begin
  61.                 DebugStr( 'Memory allocation failed!' );
  62.                 exit( ReverseTheWords );
  63.             end;
  64.             HLock(memory);
  65.             buffer := CharsArrayPtr( memory^ );
  66.         end;
  67.         
  68.         { init - I wish I could do this at compile time - Turbo Pascal can }
  69.         for i := 0 to 255 do alphanum_set[i] := false;
  70.         for i := 48 to 57 do alphanum_set[i] := true; { 0..9 }
  71.         for i := 65 to 90 do alphanum_set[i] := true; { A..Z }
  72.         for i := 97 to 122 do alphanum_set[i] := true; { a..z }
  73.  
  74.         { reverse }
  75.         leftin := 0;
  76.         leftout := leftin;
  77.         rightin := numCharsIn - 1;
  78.         rightout := rightin;
  79.         while leftin <= rightin do begin
  80.             while not alphanum_set[text^[leftin]] & (leftin <= rightin) do begin
  81.                 buffer^[leftout] := text^[leftin];
  82.                 Inc(leftout);
  83.                 Inc(leftin);
  84.             end;
  85.             while not alphanum_set[text^[rightin]] & (leftin < rightin) do begin
  86.                 buffer^[rightout] := text^[rightin];
  87.                 Dec(rightout);
  88.                 Dec(rightin);
  89.             end;
  90.             leftedge := leftin;
  91.             rightedge := rightin;
  92.             while alphanum_set[text^[leftin]] & (leftin <= rightin) do begin
  93.                 Inc(leftin);
  94.             end;
  95.             if leftin > rightin then begin { central word, just copy, ignore case }
  96.                 for i := leftedge to leftin - 1 do begin
  97.                     buffer^[leftout] := text^[i];
  98.                     Inc(leftout);
  99.                 end;
  100.             end else begin
  101.                 while alphanum_set[text^[rightin]] do begin { there is a sentinel now, we dont need to check leftin < rightin }
  102.                     Dec(rightin);
  103.                 end;
  104.                 leftchar := text^[leftedge];
  105.                 rightchar := text^[rightin+1];
  106.                 if ( leftchar > 57 ) & ( rightchar > 57 ) then begin { both letters }
  107.                     if leftchar > 90 then begin
  108.                         if rightchar <= 90 then begin
  109.                             rightchar := rightchar + $20;
  110.                             leftchar := leftchar - $20;
  111.                         end;
  112.                     end else begin
  113.                         if rightchar > 90 then begin
  114.                             rightchar := rightchar - $20;
  115.                             leftchar := leftchar + $20;
  116.                         end;
  117.                     end;
  118.                 end;
  119.                 buffer^[leftout] := rightchar;
  120.                 Inc(leftout);
  121.                 for i := rightin+2 to rightedge do begin
  122.                     buffer^[leftout] := text^[i];
  123.                     Inc(leftout);
  124.                 end;
  125.                 for i := leftin-1 downto leftedge+1 do begin
  126.                     buffer^[rightout] := text^[i];
  127.                     Dec(rightout);
  128.                 end;
  129.                 buffer^[rightout] := leftchar;
  130.                 Dec(rightout);
  131.             end;
  132.         end;
  133.         
  134.         { copy buffer }
  135.         BlockMoveData( buffer, text, numCharsIn );
  136.         
  137.         { free memory if required }
  138.         if memory <> nil then begin
  139.             DisposeHandle( memory );
  140.         end;
  141.     end;
  142.     
  143. end.
  144.